package com.lanhai.zhonglai.impl;
 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map; 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.lanhai.zhonglai.beans.AgvBean;
import com.lanhai.zhonglai.beans.DotBean;
import com.lanhai.zhonglai.dao.PowerDao;
import com.lanhai.zhonglai.dao.RoadDao;
import com.lanhai.zhonglai.dao.StationGroupDao;
import com.lanhai.zhonglai.interfaces.IAgv;
import com.lanhai.zhonglai.interfaces.IAgvEvent;
import com.lanhai.zhonglai.interfaces.IDot;
import com.lanhai.zhonglai.interfaces.IPower;
import com.lanhai.zhonglai.interfaces.IRoad;
import com.lanhai.zhonglai.interfaces.IStation;
import com.lanhai.zhonglai.mapper.PowerMapper;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
 
@Service
public class PowerImpl implements IPower{
	@Autowired
	PowerMapper powerMapper;

	@Autowired
	IDot iDot;
	
	@Autowired
	IAgv iAgv;
	
	@Autowired
	IAgvEvent iAgvEvent;
	 
	 
	@Autowired
	IRoad iRoad;
	 
	@Autowired
	JedisPool jedisPool;
 
	@Autowired
	IStation iStation;
	 
	static List<PowerDao> list=Collections.synchronizedList(new ArrayList<PowerDao>());
	Gson gson = new Gson();
	
	
	@Override
	public void init() {
		List<PowerDao> tmp=powerMapper.getPowerList();
		list.clear();
		
		if(tmp!=null&&tmp.size()>0) {
			list.addAll(tmp);
			
			String key = "powerlocklist";
			Jedis jd = jedisPool.getResource();
			Map<String,String> rmap=jd.hgetAll(key);
			jd.close();
			
			if (rmap.size() > 0) {
				// 获取缓存数据
				
				for (PowerDao pp : list) {
					String json = rmap.get(pp.getDotno() + "");
					if (json != null) {
						try {
							PowerDao x = gson.fromJson(json, PowerDao.class);
							pp.setIslock(x.isIslock());
							pp.setAgvid(x.getAgvid());
							pp.setLocktime(x.getLocktime());
						} catch (Exception e) {
						}
					}
				}
			} 
		} 
	}
	 
	 
	/**
	 * 小车回到工作岗位
	 */ 
	@Override
	public   void agvBackToWork( ) { 
		 new Thread() {

			@Override
			public void run() {
				long t=System.currentTimeMillis() ;
				PowerDao power=null;
				for(PowerDao p : list) {
					if(p.getLocktime()>0&&p.isIsdisable()==false && p.isIslock() &&p.getAgvid()>0 &&  p.getLocktime()<=t) {
						//预计解锁时间小于当前时间
						power=p;
						break;
					}
				} 
				if(power==null) {
					return  ;
				}
				 
				//找路线 
			 
				if(power.getDotno()>320&&power.getDotno()<336) {
					//镀膜的充电桩
					List<String> arr=Arrays.asList("正膜下料" ,"背膜下料","ALD干法","退火下料","碱抛下料");
					StationGroupDao sbean=iStation.fetchNextOutStation(440, 0, arr, false);
					if(sbean==null) {
						//没有可用的，再休息5分钟
						power.setLocktime(System.currentTimeMillis()+5*60000);
						savePowerToRedis(power);
						return;
					}
					/*
					if(iStation.hasEmpty(Arrays.asList( "正膜下料" ,"背膜下料"))==false){
						//没有可用的，再休息5分钟
						power.setLocktime(System.currentTimeMillis()+5*60000);
						savePowerToRedis(power);
						return;
					} 
					*/
				}
				
				if(power.getDotno()==304||power.getDotno()==308) {
					//制绒处的充电桩
					if(iStation.hasEmpty(Arrays.asList( "碱抛下料" ,"制绒下料" ))==false){
						//没有可用的，再休息5分钟
						power.setLocktime(System.currentTimeMillis()+5*60000);
						savePowerToRedis(power);
						return;
					} 
				}
			 
				
				 
				AgvBean agv=null;
				if(power.getAgvid()>0) {
					agv=iAgv.getBean(power.getAgvid());
				}
				if(agv==null) {  
					power.setAgvid(0);
					power.setIslock(false);
					power.setLocktime(0);
					savePowerToRedis(power);
					return  ;
				}
				DotBean dotb=iDot.getBean(power.getDotno());
				if(dotb==null) { 
					power.setAgvid(0);
					power.setIslock(false);
					power.setLocktime(0);
					savePowerToRedis(power);
					return  ;
				} 
				 
				//释放
				power.setAgvid(0);
				power.setIslock(false);
				power.setLocktime(0);
				savePowerToRedis(power);
				
				//回去的路
				agv.setNextRoad(dotb.getRouteRoad());
				agv.setFinishTrans(true); 
				iAgv.saveCache(agv);
				iAgvEvent.finishTrans(agv); 
			}
			 
		 }.start();
		
	 
	}
 
 
	@Override
	public  void agvArrivedPower(int agvid,int dotno ) {
		//再锁一次充电桩
		for (PowerDao p : list) {
			if (p.getDotno() == dotno) {
				if (p.getAgvid() != agvid||p.isIslock()==false) { 
					long t = System.currentTimeMillis()+20*60000;  // 一次充20分钟
					p.setIslock(true);
					p.setLocktime(t);
					p.setAgvid(agvid);
					savePowerToRedis( p);
					break;
				}
			}
		}	 
	}

	/**
	 *  
	 */
	@Override
	public boolean agvToPower(int currentDot, AgvBean agv) { 
		PowerDao power=null;
		for(PowerDao p : list) {
			if(p.getDecide()==currentDot&&p.isIsdisable()==false&& (p.isIslock()==false||p.getAgvid()==agv.getAgvId())) {
				power=p;
				break;
			}
		} 
		
		if(power==null) {
			return false;	
		}
		
		
		RoadDao roadDao=iRoad.getTransRoad(currentDot, power.getDotno()); //拿路线
		if (roadDao == null ||  roadDao.getId() <=  0) { 
			return false;
		}  
		//agv.setNextProcess(""); //保持原有的工序
		agv.setNextRoad(roadDao.getId());
		agv.setNexttStationName( "去充电" );
		iAgv.saveCache(agv);
		
		 
		long t=System.currentTimeMillis()+20*60000; //充20分钟
		power.setLocktime(t);
		power.setAgvid(agv.getAgvId());
		power.setIslock(true); 
		savePowerToRedis(power  );
		 
		iAgvEvent.toRoad(agv, roadDao.getId());
		return true;
	}


	@Override
	public void unlockPowerByDot(int dotno) {
		PowerDao power=null;
		for(PowerDao p : list) {
			if(p.getDotno()==dotno ) {
				power=p;
				break;
			}
		}  
		if(power==null) {
			return  ;
		}
		 
		if (power.getAgvid() > 0) { 
			//解锁
			int cagv=power.getAgvid();
			power.setLocktime(0);
			power.setAgvid(0);
			power.setIslock(false);
			savePowerToRedis(power);
			
			// 小车返回 
			AgvBean agv = iAgv.getBean(cagv);
			if (agv == null) {
				//解锁 
				return;
			}
			DotBean dotb = iDot.getBean(dotno);
			if (dotb == null) {
				return;
			}
			//回去的路
			agv.setNextRoad(dotb.getRouteRoad());
			agv.setFinishTrans(true); 
			agv.setNexttStationName( "返回工作岗位" );
		  
			iAgv.saveCache(agv);
			iAgvEvent.finishTrans(agv);
		}else {
			//解锁
			power.setLocktime(0);
			power.setAgvid(0);
			power.setIslock(false);
			savePowerToRedis(power);
		}
		
		
		
	}
 
	
	void savePowerToRedis(PowerDao p) { 
		new Thread() {

			@Override
			public void run() {
				String json=gson.toJson(p);
				String key = "powerlocklist";
				Jedis jd = jedisPool.getResource();
			    jd.hset(key,""+p.getDotno(),json);
				jd.close();
			}
			
		}.start(); 
	}


	@Override
	public boolean isLocked(int dotno) {
		boolean flag = false;
		for (PowerDao p : list) {
			if (p.getDotno() == dotno) {
				flag = p.isIslock();
				break;
			}
		}
		return flag;
	}


	@Override
	public void updatePowerState(int dotno, boolean disable) {
		for (PowerDao p : list) {
			if (p.getDotno() == dotno) {
				if(p.isIsdisable()!=disable) {
					p.setIsdisable(disable);
					powerMapper.updateDisable(dotno, disable?1:0);
				} 
				break;
			}
		}
	}


	@Override
	public void unlockPowerNotice(int dotno) {
		PowerDao power = null;
		for (PowerDao p : list) {
			if (p.getDotno() == dotno) {
				power = p;
				break;
			}
		}
		if (power == null||power.isIslock()==false) {
			return;
		}

		// 解锁
		power.setLocktime(0);
		power.setAgvid(0);
		power.setIslock(false);
		savePowerToRedis(power);
		 
	}


	@Override
	public synchronized void unlockPowerByAgv(int agvid) {
		 
		for (PowerDao power : list) {
			if (power.getAgvid()==agvid) {
				power.setLocktime(0);
				power.setAgvid(0);
				power.setIslock(false);
				savePowerToRedis(power);
			}
		} 
		
	}


	@Override
	public boolean hasEmpty(int dotno) {
		boolean flag=false; 
		//查找区域内+没有被禁用的+没有被锁定的充电桩
		for(PowerDao p : list) {
			if(p.getDecide()==dotno&&p.isIsdisable()==false&&  p.isIslock()==false  ) {
				flag=true;
				break;
			}
		} 
		 return flag;
	}
	
	
}
